#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/file.h>
#include <signal.h>
#include <sys/wait.h>
#include "server_loop_task.h"
#include "com_service.h"
#include "app_service.h"
#include "server_service.h"


#include <json/reader.h>
#include <json/json.h>
using namespace	Json ;


#define config_file "/data/pbjd/config.json"

void sig_handler(int sig)
{
	switch(sig) 
	{
		case SIGTERM:
		case SIGINT:
			exit(0);
			break;
	}
}

static int g_single_proc_inst_lock_fd = -1;
static const string g_sLockFile = "/cache/" + lexical_cast<string>( gsh_daemon_port ) + ".lock"  ;

void single_proc_inst_lockfile_cleanup()
{
	if(g_single_proc_inst_lock_fd != -1)
	{
		close(g_single_proc_inst_lock_fd);
		g_single_proc_inst_lock_fd = -1;
		remove(g_sLockFile.c_str()) ;
	}
}

bool is_single_proc_inst_running()
{
	g_single_proc_inst_lock_fd = open( g_sLockFile.c_str(), O_CREAT | O_RDWR, 0644);
	if(-1 == g_single_proc_inst_lock_fd)
	{
		fprintf(stderr, "Fail to open lock file(%s). Error: %s\n", g_sLockFile.c_str(), strerror(errno));
		return false;
	}

	if(0 == flock(g_single_proc_inst_lock_fd, LOCK_EX | LOCK_NB))
	{
		atexit(single_proc_inst_lockfile_cleanup);
		return true;
	}

	close(g_single_proc_inst_lock_fd);
	g_single_proc_inst_lock_fd = -1;
	return false;
}


bool get_config()
{
	int	fd = open( config_file, O_RDWR , 0644 );
	if( fd < 0 )
	{
		rlog << "open(" << config_file << ") error : " << strerror( errno )  << endl ;
		return false ;
	}

	char	buffer[1000] = { 0x00 } ;
	int ret = read( fd, buffer, 1000 );
	if( ret < 0 )
	{
		rlog << "read(" << config_file << ") error : " << strerror( errno )  << endl ;
		return false ;
	}
	
	Value root ;
	Reader reader ;	

	if ( !reader.parse( buffer, root ) )
	{
		rlog << "rjson::parse(" << config_file << ") json error" << endl ;
		return false ;
	}
		
	if( !root.isMember( "server_ip" ) 
		|| !root.isMember( "server_port" ) 
		|| !root.isMember( "server_heartbeat" ) 
		|| !root.isMember( "daemon_port" )
		|| !root.isMember( "client_idle" ) )
	{
		rlog << "rjson(" << config_file << ") error" << endl ;
		return false;
	}

	gs_server_ip = root["server_ip"].asString();
	gsh_server_port = atoi( root["server_port"].asString().c_str() ) ;
	gi_server_heartbeat = atoi( root["server_heartbeat"].asString().c_str() ) ;
	gsh_daemon_port = atoi( root["daemon_port"].asString().c_str() ) ;
	gi_client_idle = atoi( root["client_idle"].asString().c_str() ) ;
	
	cout << "server_ip=" << gs_server_ip << endl ;
	cout << "server_port=" << gsh_server_port << endl ;
	cout << "server_heartbeat=" << gi_server_heartbeat << endl ;
	cout << "daemon_port=" << gsh_daemon_port << endl ;
	cout << "client_idle=" << gi_client_idle << endl ;
	
	return true ;
}

int main( void )
{
	rlog << "\n\n\n\n\n\n" << endl ;
	rlog << "------- pbjd running ----------" << endl ;
	rlog <<  "get config" << endl ;
	if( !get_config() )
	{
		rlog << "get_config() error" << endl;
		return false ;
	}
	rlog << "get config success" << endl << endl ;

	if(!is_single_proc_inst_running())
	{
		rlog << "system is running already. exit..." << endl;
		return -1 ;
	}

	srand( time( NULL ) );

	signal( SIGPIPE, SIG_IGN ) ;
	signal( SIGTERM, sig_handler ) ;
	signal( SIGINT,  sig_handler ) ;

	rlog << "version : " << gs_daemon_version << endl ;
	
	if ( !rthreadpool::_instance().start(10) )
	{
		rlog << "rthreadpool::_instance().start() error" << endl ;
		return -1 ;
	}

	if ( !app_service::_instance().start() )
	{
		rlog << "app_service.start() error" << endl ;
		return -1 ;
	}
	
	if ( !(com_service::_instance()).start() )
	{
		rlog << "com_service.start() error" << endl ;
		return -1 ;
	}

	if ( !server_service::_instance().start() )
	{
		rlog << "server_service.start() error" << endl ;
		return -1 ;
	}

	cout << "\n\n" << endl ;

	while(true)
		sleep(5) ;

	return 0 ;
}
